/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.devs.benchmark;

import java.util.AbstractList;
import java.util.ArrayList;
import java.util.List;
import org.devs.benchmark.modeling.InportType;
import org.devs.benchmark.modeling.OutportType;
import org.devs.benchmark.modeling.ParameterType;

/**
 *
 * @author Alejandro Moreno
 */
public class Util {

    public static List<InportType> createInports(int num, Class cl) {

        ArrayList<InportType> inports = new ArrayList<InportType>();

        for (int i = 0; i < num; i++) {
            inports.add(new InportType("in_" + i, cl));
        }

        return inports;

    }

    public static List<InportType> createInports(String name, int num, Class cl) {

        ArrayList<InportType> inports = new ArrayList<InportType>();

        for (int i = 0; i < num; i++) {
            inports.add(new InportType(name + "_" + i, cl));
        }

        return inports;

    }

    public static List<OutportType> createOutports(int num, Class cl) {

        ArrayList<OutportType> inports = new ArrayList<OutportType>();

        for (int i = 0; i < num; i++) {
            inports.add(new OutportType("out_" + i, cl));
        }

        return inports;

    }

    public static List<OutportType> createOutports(String name, int num, Class cl) {

        ArrayList<OutportType> inports = new ArrayList<OutportType>();

        for (int i = 0; i < num; i++) {
            inports.add(new OutportType(name + "_" + i, cl));
        }

        return inports;

    }

    public static List<ParameterType> createDhrystoneParameters() {

        ArrayList<ParameterType> parameters = new ArrayList<ParameterType>();

        parameters.add(new ParameterType("numDhrystoneDeltExt", 1));
        parameters.add(new ParameterType("numDhrystoneDeltInt", 1));
        parameters.add(new ParameterType("period", 0.0));

        return parameters;

    }

    public static int gcd(int n, int d) {
        if (d == 0) {
            return 1;
        }
        int r = n % d;
        return (r == 0) ? d : gcd(d, r);
    }

    public static int nNodes(int height, int leafs) {
        int n = 0;
        for (int i = 0; i < height; i++) {
            n += Math.pow(leafs, i);
        }
        return n;
    }

    public static <T> List<List<T>> partition(List<T> list, int size) {

        if (list == null) {
            throw new NullPointerException(
                    "'list' must not be null");
        }
        if (!(size > 0)) {
            throw new IllegalArgumentException(
                    "'size' must be greater than 0");
        }

        return new Partition<T>(list, size);
    }

    private static class Partition<T> extends AbstractList<List<T>> {

        final List<T> list;
        final int size;

        Partition(List<T> list, int size) {
            this.list = list;
            this.size = size;
        }

        @Override
        public List<T> get(int index) {
            int listSize = size();
            if (listSize < 0) {
                throw new IllegalArgumentException("negative size: " + listSize);
            }
            if (index < 0) {
                throw new IndexOutOfBoundsException(
                        "index " + index + " must not be negative");
            }
            if (index >= listSize) {
                throw new IndexOutOfBoundsException(
                        "index " + index + " must be less than size " + listSize);
            }
            int start = index * size;
            int end = Math.min(start + size, list.size());
            return list.subList(start, end);
        }

        @Override
        public int size() {
            return (list.size() + size - 1) / size;
        }

        @Override
        public boolean isEmpty() {
            return list.isEmpty();
        }
    }
}
